#include "AARect.h"
#include "Ray.h"
#include "Console.h"


AARect::AARect()
{
	m_c1 = Vector3(-1,1,-1);
	m_c2 = Vector3(1,1,1);
	m_axis = YAXIS;
	m_norm = Vector3(0,-1,0);

	m_min = Vector3(std::min(m_c1.x, m_c2.x)-epsilon, std::min(m_c1.y, m_c2.y)-epsilon, std::min(m_c1.z, m_c2.z)-epsilon);
	m_max = Vector3(std::max(m_c1.x, m_c2.x)+epsilon, std::max(m_c1.y, m_c2.y)+epsilon, std::max(m_c1.z, m_c2.z)+epsilon);
}

AARect::AARect(Vector3 c1, Vector3 c2, int axis, Vector3 N)
: m_c1(c1), m_c2(c2)
{
//	m_min = Vector3(std::min(c1.x, c2.x), std::min(c1.y, c2.y), std::min(c1.z, c2.z));
//	m_max = Vector3(std::max(c1.x, c2.x), std::max(c1.y, c2.y), std::max(c1.z, c2.z));
	m_min = Vector3(std::min(m_c1.x, m_c2.x)-epsilon, std::min(m_c1.y, m_c2.y)-epsilon, std::min(m_c1.z, m_c2.z)-epsilon);
	m_max = Vector3(std::max(m_c1.x, m_c2.x)+epsilon, std::max(m_c1.y, m_c2.y)+epsilon, std::max(m_c1.z, m_c2.z)+epsilon);
	m_axis = axis;
	m_norm = N;
}

AARect::~AARect()
{
}

void AARect::renderGL()
{
	Vector3 v0 = m_min;
	Vector3 v1 = m_max;

	glBegin(GL_QUADS);
	switch (m_axis)
	{
	case XAXIS:
        glVertex3f(v0.x, v0.y, v0.z);
        glVertex3f(v0.x, v1.y, v0.z);
        glVertex3f(v0.x, v1.y, v1.z);
		glVertex3f(v0.x, v0.y, v1.z);
		break;
	case YAXIS:
        glVertex3f(v0.x, v0.y, v0.z);
        glVertex3f(v1.x, v0.y, v0.z);
        glVertex3f(v1.x, v0.y, v1.z);
		glVertex3f(v0.x, v0.y, v1.z);
		break;
	case ZAXIS:
        glVertex3f(v0.x, v0.y, v0.z);
        glVertex3f(v1.x, v0.y, v0.z);
        glVertex3f(v1.x, v1.y, v0.z);
		glVertex3f(v0.x, v1.y, v0.z);
		break;
	}
    glEnd();
}

void AARect::preCalc()
{
	m_min = Vector3(std::min(m_c1.x, m_c2.x)-epsilon, std::min(m_c1.y, m_c2.y)-epsilon, std::min(m_c1.z, m_c2.z)-epsilon);
	m_max = Vector3(std::max(m_c1.x, m_c2.x)+epsilon, std::max(m_c1.y, m_c2.y)+epsilon, std::max(m_c1.z, m_c2.z)+epsilon);
}

bool AARect::intersect(HitInfo& result, const Ray& ray, float tMin, float tMax)
{	
	Vector3 inv_d = Vector3(1/ray.d.x, 1/ray.d.y, 1/ray.d.z);
	float t = (m_min[m_axis] - ray.o[m_axis])*inv_d[m_axis];

	int u = (m_axis + 1) % 3;
	int v = (m_axis + 2) % 3;

	Vector3 p = ray.o + t*ray.d;
	if(t > tMin && t < tMax && (p[u] > m_min[u]) && (p[v] > m_min[v]) && (p[u] < m_max[u]) && (p[v] < m_max[v])) {
		result.t = t;
		result.P = p;
		result.N = m_norm;
		result.material = m_material;
		return true;
	}

	return false;
}
